package cloud.misiro.test.aop;

import cloud.misiro.spring.aop.AdvisedSupport;
import cloud.misiro.spring.aop.ClassFilter;
import cloud.misiro.spring.aop.TargetSource;
import cloud.misiro.spring.aop.aspectj.AspectJExpressionPointcutAdvisor;
import cloud.misiro.spring.aop.framework.CglibAopProxy;
import cloud.misiro.spring.aop.framework.JdkDynamicAopProxy;
import cloud.misiro.spring.aop.framework.ProxyFactory;
import cloud.misiro.spring.aop.framework.adapter.AfterReturningAdviceInterceptor;
import cloud.misiro.spring.aop.framework.adapter.MethodBeforeAdviceInterceptor;
import cloud.misiro.test.common.WorldServiceAfterReturningAdvice;
import cloud.misiro.test.common.WorldServiceBeforeAdvice;
import cloud.misiro.test.service.WorldService;
import cloud.misiro.test.service.WorldServiceImpl;
import org.junit.Before;
import org.junit.Test;

public class DynamicProxyTest {

    private AdvisedSupport advisedSupport;

    @Before
    public void setUp() {
        WorldService worldService = new WorldServiceImpl();
        advisedSupport = new ProxyFactory();
        String expression = "execution(* cloud.misiro.test.service.WorldService.explode(..))";
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setExpression(expression);
        AfterReturningAdviceInterceptor methodInterceptor = new AfterReturningAdviceInterceptor(new WorldServiceAfterReturningAdvice());
        advisor.setAdvice(methodInterceptor);
        TargetSource targetSource = new TargetSource(worldService);

        advisedSupport.setTargetSource(targetSource);
        advisedSupport.addAdvisor(advisor);
    }

    @Test
    public void testJdkDynamicProxy() throws Exception {
        WorldService proxy = (WorldService) new JdkDynamicAopProxy(advisedSupport).getProxy();
        proxy.explode();
    }

    @Test
    public void testCglibDynamicProxy() throws Exception {
        WorldService proxy = (WorldService) new CglibAopProxy(advisedSupport).getProxy();
        proxy.explode();
    }

    @Test
    public void testProxyFactory() throws Exception {
        ProxyFactory factory = (ProxyFactory) advisedSupport;
        factory.setProxyTargetClass(false);
        WorldService proxy = (WorldService) factory.getProxy();
        proxy.explode();

        factory.setProxyTargetClass(true);
        proxy = (WorldService) factory.getProxy();
        proxy.explode();
    }

    @Test
    public void testBeforeAdvice() throws Exception {
        String expression = "execution(* cloud.misiro.test.service.WorldService.explode(..))";
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setExpression(expression);
        MethodBeforeAdviceInterceptor methodInterceptor = new MethodBeforeAdviceInterceptor(new WorldServiceBeforeAdvice());

        advisor.setAdvice(methodInterceptor);
        advisedSupport.addAdvisor(advisor);
        ProxyFactory factory = (ProxyFactory) advisedSupport;
        WorldService proxy = (WorldService) factory.getProxy();
        proxy.explode();
    }

    @Test
    public void testAdvisor() throws Exception {
        WorldService worldService = new WorldServiceImpl();

        String expression = "execution(* cloud.misiro.test.service.WorldService.explode(..))";
        AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
        advisor.setExpression(expression);
        MethodBeforeAdviceInterceptor methodInterceptor = new MethodBeforeAdviceInterceptor(new WorldServiceBeforeAdvice());

        advisor.setAdvice(methodInterceptor);

        ClassFilter classFilter = advisor.getPointCut().getClassFilter();
        if (classFilter.matches(worldService.getClass())) {
            ProxyFactory proxyFactory = new ProxyFactory();

            TargetSource targetSource = new TargetSource(worldService);
            proxyFactory.setTargetSource(targetSource);
            proxyFactory.addAdvisor(advisor);

            WorldService proxy = (WorldService) proxyFactory.getProxy();
            proxy.explode();
        }
    }
}
